# import pickle
# import base64
# cart = {
#     '1':{'count':5,'selected':True}
# }
#
# dumps = pickle.dumps(cart)
# dumps
#
# encode = base64.b64encode(dumps)
# encode
#
# encode.decode()
#
# decode = base64.b64decode(encode)
# decode
#
# pickle.loads(decode)
import base64
import pickle

from django_redis import get_redis_connection
from rest_framework import status
from rest_framework.response import Response
from rest_framework.views import APIView

from cart.serializer import CartSerializer, CartSKUSerializer, CartDeleteSerializer
from goods.models import SKU

import redis
from redis import StrictRedis,Redis


class CartAPIView(APIView):

    def perform_authentication(self, request):
        pass

    # def post(self,requst):
    #     data = requst.data
    #
    #     serializer = CartSerializer(data=data)
    #     serializer.is_valid(raise_exception=True)
    #     sku_id = serializer.validated_data.get('sku_id')
    #     count = serializer.validated_data.get('count')
    #     selected = serializer.validated_data.get('selected')
    #
    #     try:
    #         user = requst.user
    #     except Exception as e:
    #         user = None
    #         # requst.user.is_authenticated
    #     if user is not None and user.is_authenticated:
    #         redis_conn = get_redis_connection('cart')
    #
    #         redis_conn.hset('cart_%s'%user.id,sku_id,count)
    #
    #         if selected:
    #             redis_conn.sadd('cart_selected_%s'%user.id,sku_id)
    #         return Response(serializer.data)
    #
    #     else:
    #         cookie_str = requst.COOKIES.get('cart')
    #
    #         if cookie_str is not None:
    #
    #             decode = base64.b64decode(cookie_str)
    #
    #             cookie_cart = pickle.loads(decode)
    #         else:
    #
    #             cookie_cart = {}
    #
    #         if sku_id in cookie_cart:
    #
    #             original_count = cookie_cart[sku_id]['count']
    #
    #             count += original_count
    #
    #         cookie_cart[sku_id]={
    #             'count':count,
    #             'selected':selected
    #         }
    #
    #         dumps = pickle.dumps(cookie_cart)
    #         encode = base64.b64encode(dumps)
    #
    #         response = Response(serializer.data)
    #         response.set_cookie('cart',encode.decode())
    #
    #         return response
    pass    # post 練習 添加到購物車
    def post(self,request):

        data = request.data

        serializer = CartSerializer(data=data)
        serializer.is_valid(raise_exception=True)

        sku_id = serializer.validated_data.get('sku_id')
        count = serializer.validated_data.get('count')
        selected = serializer.validated_data.get('selected')
        try:
            user = request.user
        except Exception as e:
            user = None
        # request.user.is_authenticated

        if user is not None and user.is_authenticated:

            redis_conn = get_redis_connection('cart')

            redis_conn.hset('cart_%s'%user.id,sku_id,count)

            if selected:
                redis_conn.sadd('cart_selected_%s'%user.id,sku_id)

            return Response(serializer.data)
        else:

            cookie_str = request.COOKIES.get('cart')

            if cookie_str is not None:

                decode = base64.b64decode(cookie_str)

                cookie_cart = pickle.loads(decode)

            else:
                cookie_cart = {}

            if sku_id in cookie_cart:

                original_count = cookie_cart[sku_id]['count']

                count += original_count

            cookie_cart[sku_id] = {

                'count':count,
                'selected':selected
            }

            dumps = pickle.dumps(cookie_cart)
            encode = base64.b64encode(dumps)

            response = Response(serializer.data)
            response.set_cookie('cart',encode.decode())

            return response
    pass    # post 練習
    # def post(self,request):
    #
    #     data = request.data
    #
    #     serializer = CartSerializer(data=data)
    #     serializer.is_valid(raise_exception=True)
    #
    #     sku_id = serializer.validated_data.get('sku_id')
    #     count = serializer.validated_data.get('count')
    #     selected = serializer.validated_data.get('selected')
    #     try:
    #         user = request.user
    #     except Exception as e:
    #         user = None
    #
    #     if user is not None and user.is_authenticated:
    #
    #         redis_conn = get_redis_connection('cart')
    #         # hash
    #         # redis_conn.hset('cart_%s'%user.id,sku_id,count)
    #         redis_conn.hincrby('cart_%s'%user.id,sku_id,count)
    #
    #         pl = redis_conn.pipeline()
    #         pl.hincrby('cart_%s'%user.id,sku_id,count)
    #
    #         # set
    #         if selected:
    #             redis_conn.sadd('cart_selected_%s'%user.id,sku_id)
    #             pl.sadd('cart_selected_%s'%user.id,sku_id)
    #
    #         pl.execute()
    #
    #         return Response(serializer.data)
    #
    #     else:
    #
    #         cookie_str = request.COOKIES.get('cart')
    #
    #         if cookie_str is not None:
    #
    #             decode = base64.b64decode(cookie_str)
    #             cookie_cart = pickle.loads(decode)
    #         else:
    #             cookie_cart = {}
    #
    #         if sku_id in cookie_cart:
    #             original_count = cookie_cart[sku_id]['count']
    #
    #             count += original_count
    #         cookie_cart[sku_id] = {
    #             'count':count,
    #             'selected':selected
    #         }
    #
    #         dumps = pickle.dumps(cookie_cart)
    #         encode = base64.b64encode(dumps)
    #
    #         response = Response(serializer.data)
    #         response.set_cookie('cart',encode.decode())
    #
    #         return response
    pass    # post 復制

    def get(self,request):

        try:
            user = request.user
        except Exception as e:
            user = None

        if user is not None and request.user.is_authenticated:

            redis_conn = get_redis_connection('cart')

            sku_id_counts = redis_conn.hgetall('cart_%s'%user.id)

            selected_ids = redis_conn.smembers('cart_selected_%s'%user.id)

            cookie_cart = {}

            for sku_id,count in sku_id_counts.items():


                cookie_cart[int(sku_id)] = {
                    'count':int(count),
                    'selected':sku_id in selected_ids
                }

        else:

            cookie_str = request.COOKIES.get('cart')

            if cookie_str is not None:

                cookie_cart = pickle.loads(base64.b64decode(cookie_str))

            else:
                cookie_cart = {}

        ids = cookie_cart.keys()

        skus = SKU.objects.filter(pk__in=ids)

        for sku in skus:
            # sku.count = cart[sku.id]['count']
            # sku.selected = cart[sku.id]['selected']
            sku.count = cookie_cart[sku.id]['count']
            # sku.selected = cookie_cart[sku.id]['selected']
            sku.selected = cookie_cart[sku.id]['selected']

        serializer = CartSKUSerializer(skus,many=True)

        return Response(serializer.data)# pass
    pass    # get練習 獲取購物車
    # def get(self, request):
    #     """
    #     思路
    #     #判断是否为登录用户
    #         #登录用户,从redis中获取数据
    #         #非登录用户,从cookie中获取数据
    #     #获取所有商品的信息
    #     #返回响应
    #     """
    #     try:
    #         user = request.user
    #     except Exception:
    #         user = None
    #     # 判断是否为登录用户
    #     if user is not None and user.is_authenticated:
    #         # 登录用户,从redis中获取数据
    #         redis_conn = get_redis_connection('cart')
    #         redis_cart = redis_conn.hgetall('cart_%s' % user.id)
    #         redis_cart_select = redis_conn.smembers('cart_selected_%s' % user.id)
    #         cart = {}
    #         for sku_id, count in redis_cart.items():
    #             cart[int(sku_id)] = {
    #                 'count': int(count),
    #                 'selected': sku_id in redis_cart_select
    #             }
    #
    #     else:
    #         # 非登录用户,从cookie中获取数据
    #         cart_str = request.COOKIES.get('cart')
    #
    #         if cart_str is not None:
    #             cart = pickle.loads(base64.b64decode(cart_str.encode()))
    #         else:
    #             cart = {}
    #
    #     # 获取所有商品的信息
    #     skus = SKU.objects.filter(id__in=cart.keys())
    #     for sku in skus:
    #         sku.count = cart[sku.id]['count']
    #         sku.selected = cart[sku.id]['selected']
    #     # 序列化数据,并返回响应
    #     serializer = CartSKUSerializer(skus, many=True)
    #
    #     return Response(serializer.data)
    pass    # get 復制
    # def get(self, request):
    #     # 1.获取用户信息
    #     try:
    #         user = request.user
    #     except Exception as e:
    #         user = None
    #     # 2.根据用户信息进行判断
    #     # request.user.is_authenticated
    #     if user is not None and user.is_authenticated:
    #         # 3.登陆用户从redis中获取数据
    #         #     3.1 连接redis
    #         redis_conn = get_redis_connection('cart')
    #         #     3.2 获取hash
    #         # {sku_id:count}
    #         sku_id_counts = redis_conn.hgetall('cart_%s' % user.id)
    #         # ,set 选中的id
    #         # [sku_id]
    #         selected_ids = redis_conn.smembers('cart_selected_%s' % user.id)
    #         #     3.3 都获取商品id，count，selected
    #
    #         """
    #         因为redis获取的数据格式 和 cookie获取的数据格式不一致
    #         所以 根据id去获取商品的详细信息的业务逻辑不能统一
    #
    #         我们就选择让数据 统一就行了
    #
    #         为什么选择将 redis数据转换为 cookie格式
    #         redis但是数据获取之后都是 bytes
    #
    #         # cookie_cart = {sku_id:{count:xxx,selected:True}}
    #         """
    #         cookie_cart = {}
    #         for sku_id, count in sku_id_counts.items():
    #
    #             # sku_id 4
    #             # selected_ids = [1,2,3]
    #             # selected_ids 保存的是 选中商品的id
    #
    #             if sku_id in selected_ids:
    #                 flag = True
    #             else:
    #                 flag = False
    #
    #             cookie_cart[int(sku_id)] = {
    #                 'count': int(count),
    #                 'selected': sku_id in selected_ids  # flag
    #             }
    #     else:
    #         # 4.未登录用户从cookie中获取数据
    #         #     4.1 获取cookie数据
    #         cookie_str = request.COOKIES.get('cart')
    #         #     4.2 判断cart数据
    #         if cookie_str is not None:
    #             #         如果有则进行解密
    #             # cookie_cart = {sku_id:{count:xxx,selected:True}}
    #             cookie_cart = pickle.loads(base64.b64decode(cookie_str))
    #         else:
    #             #         如果没有就是空
    #             cookie_cart = {}
    #             #     4.3.都获取商品id，count，selected
    #
    #     # cookie_cart = {sku_id:{count:xxx,selected:True},sku_id:{count:xxx,selected:True},}
    #     # 5.根据id去获取商品的详细信息 sku
    #     ids = cookie_cart.keys()  # [1,3,4,5,6]
    #     skus = SKU.objects.filter(pk__in=ids)  # [sku,sku,sku]
    #
    #     # 对 skus 进行遍历
    #     for sku in skus:
    #         sku.count = cookie_cart[sku.id]['count']
    #         sku.selected = cookie_cart[sku.id]['selected']
    #
    #     # 6.将对象转换为字典
    #     serializer = CartSKUSerializer(skus, many=True)
    #
    #     return Response(serializer.data)
    pass    # get 老師代碼
    # def put(self, request):
    #     """
    #     修改购物车数据
    #     思路:
    #     # 创建序列化,校验数据
    #     #获取数据
    #     #获取用户
    #     #判断用户是否为登录用户
    #          #登录用户,从redis中获取数据
    #         #非登录用户,从cookie中获取数据
    #     """
    #     # 创建序列化,校验数据
    #     serializer = CartSerializer(data=request.data)
    #     serializer.is_valid(raise_exception=True)
    #     sku_id = serializer.data.get('sku_id')
    #     count = serializer.data.get('count')
    #     selected = serializer.data.get('selected')
    #     # 获取用户
    #     try:
    #         user = request.user
    #     except Exception:
    #         user = None
    #     # 判断用户是否为登录用户
    #     if user is not None and user.is_authenticated:
    #         # 登录用户,从redis中获取数据
    #         redis_conn = get_redis_connection('cart')
    #         pl = redis_conn.pipeline()
    #
    #         # 更新数据
    #         pl.hset('cart_%s' % user.id, sku_id, count)
    #         # 更改状态
    #         if selected:
    #             pl.sadd('cart_selected_%s' % user.id, sku_id)
    #         else:
    #             pl.srem('cart_selected_%s' % user.id, sku_id)
    #         pl.execute()
    #         return Response(serializer.data)
    #     else:
    #         # 非登录用户,从cookie中获取数据
    #         cart_str = request.COOKIES.get('cart')
    #         if cart_str is not None:
    #             cart = pickle.loads(base64.b64decode(cart_str.encode()))
    #         else:
    #             cart = {}
    #
    #         if sku_id in cart:
    #             cart[sku_id] = {
    #                 'count': count,
    #                 'selected': selected
    #             }
    #
    #         cookie_str = base64.b64encode(pickle.dumps(cart)).decode()
    #
    #         response = Response(serializer.data)
    #         response.set_cookie('cart', cookie_str)
    #
    #         return response
    pass    #  put 課本代碼
    # def put(self,request):
    #     data = request.data
    #
    #     serializser = CartSerializer(data=data)
    #     serializser.is_valid(raise_exception=True)
    #
    #     sku_id = serializser.validated_data.get('sku_is')
    #     count = serializser.validated_data.get('count')
    #     selected = serializser.validated_data.get('selected')
    #
    #     try:
    #         user = request.user
    #     except Exception as e:
    #         user = None
    #     # request.user.is_authenticated
    #     if user is not None and user.is_authenticated:
    #
    #         redis_conn = get_redis_connection('cart')
    #         redis_conn.hset('cart_%s'%user.id,sku_id,count)
    #
    #         if selected:
    #             redis_conn.sadd('cart_selected%s'%user.id,sku_id)
    #         else:
    #             redis_conn.srem('cart_selected%s'%user.id,sku_id)
    #
    #         return Response(serializser.data)
    #     else:
    #
    #         cookie_str = request.COOKIES.get('cart')
    #
    #         if cookie_str is not None:
    #             cook_cart = pickle.loads(base64.b64decode(cookie_str))
    #         else:
    #             cookie_str = {}
    #
    #         if sku_id in cookie_str:
    #             cookie_str[sku_id]={
    #                 'count':count,
    #                 'selected':selected
    #             }
    #         cookie_encode = base64.b64encode(pickle.dumps(cookie_str))
    #         response = Response(serializser.data)
    #         response.set_cookie('cart',cookie_encode.decode())
    #
    #         return response
    #
    #     pass
    pass    # put 練習
    def put(self, request):
        serializer = CartSerializer(data=request.data)
        serializer.is_valid(raise_exception=True)
        sku_id = serializer.data.get('sku_id')
        count = serializer.data.get('count')
        selected = serializer.data.get('selected')

        try:
            user = request.user
        except Exception:
            user = None

        if user is not None and user.is_authenticated:
            redis_conn = get_redis_connection('cart')
            pl = redis_conn.pipeline()

            pl.hset('cart_%s' % user.id,sku_id,count)

            if selected:
                pl.sadd('cart_selected_%s'%user.id,sku_id)
            else:
                pl.srem('cart_selected_%s'%user.id,sku_id)
            pl.execute()
            return Response(serializer.data)
        else:

            cart_str = request.COOKIES.get('cart')
            if cart_str is not None:
                cart = pickle.loads(base64.b64decode(cart_str.encode()))
            else:
                cart = {}

            if sku_id in cart:
                cart[sku_id] = {
                    'count':count,
                    'selected':selected
                }
            cookie_str = base64.b64encode(pickle.dumps(cart)).decode()
            response = Response(serializer.data)
            response.set_cookie('cart',cookie_str)

            return response

        pass
    pass    # put 練習 修改購物車數據

    def delete(self, request):
        """
        删除数据
        思路
        #获取提交数据,并进行校验
        #获取校验之后的数据
        #获取user信息
        #判断是否登录
            #登录用户,从redis中删除数据
            #非登录用户,从cookie中删除数据
        """
        # 获取提交数据,并进行校验
        serializer = CartDeleteSerializer(data=request.data)
        serializer.is_valid(raise_exception=True)
        # 获取校验之后的数据
        sku_id = serializer.data.get('sku_id')
        # 获取user信息
        try:
            user = request.user
        except Exception:
            user = None
        # 判断是否登录
        if user is not None and user.is_authenticated:
            # 登录用户,从redis中删除数据
            redis_conn = get_redis_connection('cart')
            pl = redis_conn.pipeline()
            pl.hdel('cart_%s' % user.id, sku_id)
            pl.srem('cart_selected_%s' % user.id, sku_id)
            pl.execute()
            return Response(status=status.HTTP_204_NO_CONTENT)
        else:
            # 非登录用户,从cookie中删除数据
            cart_str = request.COOKIES.get('cart')

            if cart_str is not None:
                cart = pickle.loads(base64.b64decode(cart_str.encode()))
            else:
                cart = {}

            response = Response(serializer.data)

            if sku_id in cart:
                del cart[sku_id]
                # 组织数据
                cookie_str = base64.b64encode(pickle.dumps(cart)).decode()
                response.set_cookie('cart', cookie_str)

            return response
    pass    # 老師代碼  刪除購物車 數據


